package com.gcstorage.tvdev.net;


import android.telephony.mbms.DownloadProgressListener;

import com.blankj.utilcode.util.AppUtils;
import com.blankj.utilcode.util.DeviceUtils;
import com.blankj.utilcode.util.LogUtils;
import com.blankj.utilcode.util.NetworkUtils;
import com.gcstorage.tvdev.constants.CustomTrust;
import com.gcstorage.tvdev.util.SpUtils;

import java.io.IOException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import okhttp3.tls.HandshakeCertificates;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;

public class RetrofitManager {
    private static final long CONNECT_TIMEOUT = 5;
    private static final long READ_TIMEOUT = 30;
    private static RetrofitManager instance;

    public static RetrofitManager getInstance() {
        if (instance == null) {
            synchronized (RetrofitManager.class) {
                if (instance == null) {
                    instance = new RetrofitManager();
                }
            }
        }
        return instance;
    }

    private RetrofitManager() {
    }

    private HttpApi httpApi;

    public HttpApi createApiService() {
        if (httpApi == null) {
            synchronized (RetrofitManager.class) {
                if (httpApi == null) {
                    Retrofit retrofit = new Retrofit.Builder()
                            .baseUrl("https://square.github.io/retrofit/")
                            .addConverterFactory(GsonConverterFactory.create())
                            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                            .client(getOkHttpClient(false, null))
                            .build();
                    httpApi = retrofit.create(HttpApi.class);
                }
            }
        }
        return httpApi;
    }

    private HttpApi downLoadApi;

    public HttpApi createAPIService(boolean isDownLoadFile, DownloadProgressListener listener) {
        if (downLoadApi == null) {
            synchronized (RetrofitManager.class) {
                if (downLoadApi == null) {
                    Retrofit retrofit = new Retrofit.Builder()
                            .baseUrl("https://square.github.io/retrofit/")
                            .addConverterFactory(GsonConverterFactory.create())
                            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                            .client(getOkHttpClient(isDownLoadFile, listener))
                            .build();
                    downLoadApi = retrofit.create(HttpApi.class);
                }
            }
        }
        return downLoadApi;
    }

    private OkHttpClient getOkHttpClient(boolean isDownLoadFile, DownloadProgressListener listener) {
        OkHttpClient.Builder builder = getClientBuilder();
        if (isDownLoadFile)
            return builder
                    .addInterceptor(new DownloadInterceptor(listener))
                    .build();
        HttpLoggingInterceptor logInterceptor = new HttpLoggingInterceptor(it -> {
            LogUtils.i("OkHttp", it);
        });
        logInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        builder.addInterceptor(logInterceptor);
        HandshakeCertificates certificates = CustomTrust.getCertificates();
        builder.sslSocketFactory(certificates.sslSocketFactory(), certificates.trustManager());
        builder.hostnameVerifier((hostname, session) -> true);
//        builder.sslSocketFactory(createSSLSocketFactory());
        return builder.build();
    }

    private OkHttpClient.Builder getClientBuilder() {
        return new OkHttpClient.Builder()
                .connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS)
                .readTimeout(READ_TIMEOUT, TimeUnit.SECONDS)
                .writeTimeout(READ_TIMEOUT, TimeUnit.SECONDS)
                .addInterceptor(netInterceptor)
                .addInterceptor(new ErrorResInterceptor())
                .followRedirects(true)
                .retryOnConnectionFailure(true);
    }

    private final Interceptor netInterceptor = new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {
            if (!NetworkUtils.isConnected()) {
                throw new CustomException(CustomException.NO_NET, "网络没有连接,请检查网络");
            }
            Request request = chain.request();
            if (!request.url().toString().contains("/file-oss/")) {//文件接口不传头文件
                request = request.newBuilder()
                        .addHeader("Blade-Auth", SpUtils.getString(SpUtils.TAG_USER, "user_token_type", "") + " " + SpUtils.getString(SpUtils.TAG_USER, "user_access_token", ""))
                        .addHeader("Authorization", SpUtils.getString("clientId"))
                        .addHeader("manufacturer", DeviceUtils.getManufacturer())
                        .addHeader("model", DeviceUtils.getModel())
                        .addHeader("deviceId", DeviceUtils.getUniqueDeviceId())
                        .addHeader("appVersion", AppUtils.getAppVersionName())
                        .addHeader("User-Type", "app")
                        .addHeader("timeMillis", System.currentTimeMillis() + "")
                        .addHeader("userId", SpUtils.getString(SpUtils.TAG_USER, "user_id", ""))
                        .addHeader("Tenant-Id", SpUtils.getString("tenantId"))
                        .addHeader("tenantId", SpUtils.getString("tenantId"))
                        .build();
            }

            return chain.proceed(request);
        }
    };

    private SSLSocketFactory createSSLSocketFactory() {
        SSLSocketFactory ssfFactory = null;
        try {
            SSLContext sc = SSLContext.getInstance("SSL");
            sc.init(null, new TrustManager[]{new MyTrustManager()}, new SecureRandom());
            ssfFactory = sc.getSocketFactory();
        } catch (Exception ignored) {
            ignored.printStackTrace();
        }

        return ssfFactory;
    }

    //实现X509TrustManager接口
    public static class MyTrustManager implements X509TrustManager {
        @Override
        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        }

        @Override
        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        }

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[0];
        }
    }
}
